#pragma once

#include <TopoDS_Wire.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Shape.hxx>
#include <TopTools_ListOfShape.hxx>
#include <TopoDS_Compound.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Solid.hxx>
#include <TopoDS_Shell.hxx>

extern bool RemoveEdgeFromWire(const TopoDS_Wire& originalWire, const TopoDS_Edge& edgeToRemove, TopoDS_Shape& remainingShape);// 剩余部分（可能多个Segment)

// 辅助函数：将Edge列表转为Wire并加入Compound
extern void AddSegmentToCompound(const TopTools_ListOfShape& edges, TopoDS_Compound& compound);

// 从 shape 移除指定的face
extern TopoDS_Shape removeFaceFromShape(const TopoDS_Shape& solidShape, const TopoDS_Face& faceToRemove);

// 是否存在 >=num 个面
extern bool hasMoreThanNumFace(const TopoDS_Shape& shape, int num = 1);

// 获得sub shape 的index
extern int GetSubShapeIndex(const TopoDS_Shape& shape, TopAbs_ShapeEnum type, const TopoDS_Shape& subShape);

// 根据 index 获得 sub shape
extern TopoDS_Shape GetSubShapeByIndex(const TopoDS_Shape& shape, TopAbs_ShapeEnum type, int index);

// 移除指定face，但保留边界
extern TopoDS_Shape RemoveFaceAndKeepBoundary(const TopoDS_Shape& shape, const TopoDS_Face& faceToRemove);

/**
 * @brief 将一个开放的、只缺少一个面的壳封闭成一个实体。
 *
 * @param openShellShape 包含开放壳的 TopoDS_Shape。
 * @return TopoDS_Solid 如果成功，返回创建的实体；否则返回一个空的实体。
 */
extern TopoDS_Solid CloseOpenShellToSolid(const TopoDS_Shape& openShellShape);

/**
 * @brief 尝试将一个输入的 TopoDS_Shape 转换为 TopoDS_Shell。
 *
 * 这个函数能处理 Shell, Solid, Compound, 和 Face 类型的输入。
 * - 如果是 Shell，直接返回。
 * - 如果是 Solid，返回其第一个外壳。
 * - 如果是 Compound，提取其中的所有 Face 组成一个新的 Shell。
 * - 如果是 Face，创建一个包含该 Face 的新 Shell。
 * - 其他情况，返回一个空的 Shell。
 *
 * @param inputShape 要转换的形状。
 * @return TopoDS_Shell 转换得到的壳。如果转换失败，返回的壳 IsNull() 会是 true。
 */
extern TopoDS_Shell ConvertToShell(const TopoDS_Shape& inputShape);

/**
 * @brief 在一个平面的Face或Wire上，通过移动一条边来将其放大或缩小。
 * * 此函数会正确处理拓扑连续性，即在移动目标边的同时，会同步更新其相邻的两条边，
 * 从而保持Wire的封闭和Face的有效性。
 * * @param aShape 输入的几何体，可以包含面(Face)或线框(Wire)。
 * @param aEdge 要移动的边。
 * @param anOffsetDistance 偏移距离。正数表示向外扩大，负数表示向内缩小。
 * @return TopoDS_Shape 包含修改后几何体的新Shape。如果操作失败，返回空的Shape。
 */
extern TopoDS_Shape OffsetEdgeInPlanarShape(const TopoDS_Shape& aShape, const TopoDS_Edge& aEdge, const Standard_Real anOffsetDistance);

/**
 * @brief 计算一个 Solid 与指定坐标平面的交集。
 * * @param solidShape 待切割的 TopoDS_Shape。函数会首先验证它是否为一个 Solid。
 * @param planeType 一个int，指定坐标平面："XY", "YZ", 或 "XZ"。
 * @return TopoDS_Shape 返回计算出的截面。如果输入无效或计算失败，则返回一个 null shape。
 */
extern TopoDS_Shape CreateSectionFromSolid(const TopoDS_Shape& solidShape, const int& planeType);

/**
 * @brief 创建一个立体螺旋结构.
 * * @param aProfile            扫掠的轮廓 (可以是 TopoDS_Wire 或 TopoDS_Face).
 * @param aCenter             螺旋中心点.
 * @param aDirection          螺旋轴线方向 (上升方向或法线方向).
 * @param bRightDirection     螺旋方向 (左手或右手).
 * @param aPitch              螺距: 每圈上升的高度. 若为 0 则是平面螺旋结构
 * @param aTurns              总圈数.
 * @param aRadiusChangePerTurn 每圈的半径变化量.
 * @param aStartRadius        螺旋的起始半径.
 * @return TopoDS_Shape       生成的实体螺旋结构.
 */
extern TopoDS_Shape createHelicalSolid(const TopoDS_Shape& aProfile,
    const gp_Pnt& aCenter,
    const gp_Dir& aDirection,
    const bool bRightDirection,
    const Standard_Real aPitch,
    const Standard_Real aTurns,
    const Standard_Real aRadiusChangePerTurn,
    const Standard_Real aStartRadius);